/* =======================================================================
 * Sistemi Operativi, Corso di Laurea in Ingegneria Informatica, DM 270/04
 * A.A. 2011/2012, Facoltà di Ingegneria, Università della Calabria
 * =======================================================================
 */

package sisop.appelli.a2012.treaule;

import java.util.concurrent.Semaphore;

/**
 * @author Marco Lackovic <mlackovic@deis.unical.it>
 * @version 1.0, Jul 27, 2012
 */
public class AuleSem extends Aule {

	/*
	 * Questo semaforo serve per sospendere gli studenti e quindi risvegliarli
	 * ad uno ad uno, in ordine FIFO.
	 */
	private Semaphore studenti = new Semaphore(0, true);

	/*
	 * Questo semaforo serve per sospendere il docente nello stato iniziale,
	 * quando gli studenti non sono ancora arrivati e in quello finale quando
	 * non ce ne sono più.
	 */
	private Semaphore studentiDaChiamare = new Semaphore(0);

	/*
	 * Questo semaforo serve per sospendere il docente in modo che aspetti che
	 * lo studente che ha fatto entrare nell'aula completi la sua operazione,
	 * prima di chiamare lo studente successivo.
	 */
	private Semaphore studenteSuccessivo = new Semaphore(1);

	/*
	 * Questo semaforo serve per sospendere il docente quando sono terminati i
	 * posti in tutt'e tre le aule.
	 */
	private Semaphore docente = new Semaphore(totalePostiDisponibili);

	/*
	 * Questo semaforo serve per far accedere alle variabili condivise in mutua
	 * esclusione al docente, e agli studenti che escono.
	 */
	private Semaphore mutex = new Semaphore(1);

	@Override
	public int accedi() throws InterruptedException {
		studentiDaChiamare.release();
		studenti.acquire();
		int miaAula = aulaProssimoStudente;
		mutex.release();
		studenteSuccessivo.release();
		return miaAula;
	}

	@Override
	public void esci(int aula) throws InterruptedException {
		mutex.acquire();
		postiDisponibili[aula]++;
		mutex.release();
		docente.release();
	}

	@Override
	public void chiamaStudente() throws InterruptedException {
		studentiDaChiamare.acquire();
		docente.acquire();
		studenteSuccessivo.acquire();
		mutex.acquire();
		aggiornaAule();
		studenti.release();
	}

}
